<template>
  <div class="gnb-markdown h100p border-box"
       v-show="selectedItem"
  >
    <div v-if="isEditMode" class="flex-column h100p">
      <div class="pa-xs mt-xs flex-not-shk">
        <el-input placeholder="请输入内容"
                  size="large"
                  v-model="title"
                  @keydown.ctrl="onEditorCtrlDown"
        >
          <template #prepend>标题</template>
        </el-input>
      </div>
      <div class="toolbar plr-xs  flex-not-shk flex-horiz flex-center mlr-xs color-text"
      >
        <div class="func-button" title="预览模式">
          <i class="iconfont icon-editor-preview"
             @click="isEditMode = false"
          ></i>
        </div>
        <div class="func-button" title="粗体">
          <i class="iconfont icon-editor-font-bold"
             @click="insertEditorContent('**','**')"
          ></i>
        </div>
        <div class="func-button" title="斜体">
          <i class="iconfont icon-editor-italic"
             @click="insertEditorContent('*','*')"
          ></i>
        </div>
        <div class="func-button" title="引用">
          <i class="iconfont icon-editor-quotation-marks-left"
             @click="insertEditorContent('>','')"
          ></i>
        </div>
        <div class="func-button" title="代码">
          <i class="iconfont icon-editor-code"
             @click="insertEditorContent('\n```js\n','\n```\n')"
          ></i>
        </div>
        <div class="func-button" title="标题1">
          <span
              @click="insertEditorContent('#','')"
          >H<sub>1</sub></span>
        </div>
        <div class="func-button" title="标题2">
          <span
              @click="insertEditorContent('##','')"
          >H<sub>2</sub></span>
        </div>
        <div class="func-button" title="标题3">
          <span
              @click="insertEditorContent('###','')"
          >H<sub>3</sub></span>
        </div>
      </div>
      <div class="plr-xs flex-grow h0 "
      >
        <splitpanes>
          <pane min-size="10" class="h100p flex-column ">
          <textarea class="scroll-thin flex-grow border-box bca-border-light pa-sm mb-xs edit-window"
                    contenteditable="true"
                    v-model="editContent"
                    ref="textareaRef"

                    @scroll="onEditorScroll"
                    @keydown.ctrl="onEditorCtrlDown"
                    @keydown.tab="onEnterTab"
          ></textarea>
          </pane>
          <pane min-size="10" class="h100p flex-column ">
            <div
                class="scroll-thin scroll-y flex-grow border-box bca-border-light pa-sm mb-xs markdown-preview theme-mo"
                v-html="formattedContent"
                ref="editPreviewRef"
            ></div>
          </pane>
        </splitpanes>
      </div>
    </div>
    <div v-else class="flex-column h100p border-box">
      <div class="ma-sm pa-sm fz-title color-text bcb-border flex-horiz flex-center">
        <div class="mr-sm">
          <el-button
              icon="el-icon-edit"
              circle
              title="点击编辑"
              @click="isEditMode = true"
          ></el-button>
        </div>
        <div>{{ title }}</div>
      </div>
      <div class="markdown-preview scroll-thin scroll-y plr-md pb-lg theme-mo  flex-grow h0  border-box"
           v-html="formattedContent"
           ref="previewRef"
      >
      </div>
    </div>

  </div>
</template>

<script lang="ts">
import {useStore} from "vuex";
import {computed, getCurrentInstance, onBeforeUnmount, ref, toRaw, watch} from "vue";
import {IpcRenderer} from "@/utils/render/common";
import "@/assets/styles/markdown/mo.content.less"
import "@/assets/styles/markdown/themes/github.gnb.less"
import 'highlight.js/styles/github.css';
import {CommonListener} from "@/utils/listener.utils";
import {debounce} from "@/utils/throttle-debounce.utils";

const hljs = require("highlight.js");

const md = require('markdown-it')({
  highlight: function (str, lang) {
    if (lang && hljs.getLanguage(lang)) {
      try {
        return `<pre class="hljs"><code>${hljs.highlight(lang, str, true).value}</code></pre>`
      } catch (_) {
      }
    }
    return `<pre class="hljs"><code>${md.utils.escapeHtml(str)}</code></pre>`
  },
  html: true,
  linkify: true,
  typographer: true
});

const defaultImageRender = md.renderer.rules.image;
md.renderer.rules.image = (tokens, idx, options, env, self) => {
  const token = tokens[idx],
      src = token.attrIndex('src');
  const t = IpcRenderer.sendSync("readImage", token.attrs[src][1]);
  return `<div class="text-center" style="max-width: 100%;"><img src="${t}" style="" /></div>`;
}


export default {
  name: 'gnb-markdown',
  mixins: [],
  components: {},
  props: {},
  data() {
    return {}
  },
  setup() {
    const store = useStore();
    const instance = getCurrentInstance();

    const title = ref("");
    const isEditMode = ref(false);
    const setEditMode = (value) => {
      isEditMode.value = value;
    }

    const removeEdit = CommonListener.addListener("setEditMode", setEditMode);
    onBeforeUnmount(() => {
      removeEdit();
    })

    const selectedItem = computed(() => store.state.note.selectedItem);

    if (selectedItem.value) title.value = selectedItem.value.name;

    watch(title, (v) => {
      if (!selectedItem.value) return;
      selectedItem.value.rename = title.value;
    })

    watch(
        selectedItem,
        (v, o) => {
          if (o) saveFile(o);
          if (!v) return;
          title.value = v.name;
          IpcRenderer.invoke("readFile", toRaw(v)).then(resp => {
            editContent.value = resp;
            ['previewRef', 'editPreviewRef', 'textareaRef'].forEach(ref => {
              if (!instance.refs[ref]) return;
              (instance.refs[ref] as Element).scrollTo(0, 0);
            })
          });
        }
    )

    const formattedContent = ref("");
    const editContent = ref("");

    watch(editContent, (v, o) => {
      formattedContent.value = md.render(v);
    });

    const onEditorScroll = (e) => {
    }

    const onEditorCtrlDown = (e) => {
      if (e.key === 's') saveFile(selectedItem.value);
    }

    const saveFile = async (item) => {
      const res = IpcRenderer.invoke("saveItem", toRaw(item), editContent.value);
      if (item.name !== item.rename) {
        item.name = item.rename;
      }
    }

    const onEnterTab = (e) => {
      e.preventDefault();
      insertEditorContent("\t");
    }

    const insertEditorContent = (startContent, endContent = "") => {
      const textarea = instance.refs['textareaRef'] as { selectionStart, selectionEnd, focus };
      const start = textarea.selectionStart;
      const end = textarea.selectionEnd;
      const s = editContent.value.slice(0, end) + endContent + editContent.value.slice(end);
      editContent.value = s.slice(0, start) + startContent + s.slice(start);
      setTimeout(() => {
        textarea.focus();
        textarea.selectionStart = start + startContent.length;
        textarea.selectionEnd = textarea.selectionStart + (end - start);
      });
    }

    watch(isEditMode, debounce((v) => {
      if (v) {
        const textarea = instance.refs['textareaRef'] as { addEventListener };
        if (!textarea) return;
        textarea.addEventListener("paste", (e) => {
          const {items} = e.clipboardData;
          if (!items.length) return;
          const item = items[0];
          if (e.clipboardData.types[0] !== 'Files') return;
          if (item.kind !== 'file' || !item.type.match(/^image\//i)) return;
          const file = item.getAsFile();
          const reader = new FileReader();
          reader.onload = (e) => {
            const path = IpcRenderer.sendSync("saveImage", e.target.result);
            console.log(333, path);
            if (!path) return;
            insertEditorContent(`\n![image](${path})`);
          }
          reader.readAsDataURL(file);
        })
      }
    }, 20) as (v, o) => void);


    return {
      selectedItem,
      title,
      formattedContent,
      editContent,
      isEditMode,

      onEditorScroll,
      onEditorCtrlDown,
      onEnterTab,
      insertEditorContent,
    }
  },
  computed: {},
  watch: {},
  created() {
  },
  mounted() {
  },
  beforeUnmount() {
  },
  activated() {
  },
  deactivated() {
  },
  methods: {}
};
</script>

<style scoped lang="less">
.gnb-markdown {
}

.edit-window {
  outline: none;
  resize: none;
  font-size: 14px;
  font-family: "Fira Code", Consolas, "Lucida Console", "Courier", monospace, "Helvetica Neue", Helvetica, Arial, sans-serif, '微软雅黑' !important;

  &:focus {
    border: 1px solid #40a9ff;
  }
}

.toolbar {
  height: 40px;
  border-radius: 4px 4px 0 0;
  background-color: #e2e2e2;

  .func-button {
    padding: 0 7px 0 7px;
    cursor: pointer;

    &:hover {
      color: #40a9ff;
    }

    &:not(:first-of-type) {
      border-left: 1px solid #fff;
    }
  }
}

textarea {

}
</style>